const regExpSymbol = Symbol("regExpSymbol");
const headerStr = Symbol("headerStr");

/**
 * 字符串工具类
 */
class StringTools {
	static instance;

	/**
	 * 调用此静态方法实现单例
	 * */
	static getInstance() {
		if (false === this.instance instanceof this) {
			this.instance = new this;
			// console.log("创建新对象");
		}
		return this.instance;
	}

	/** 构造函数*/
	constructor() {
		/**设置私有成员属性*/
		this[regExpSymbol] = ["\\", "*", ".", "?", "+", "$", "^", "[", "]", "(", ")", "{", "}", "|", "/"];

		/**设置私有成员函数*/
		this[headerStr] = function (str) {
			if(str === undefined || str === null){
				str = str || "";
			}
			if (typeof str == "object") {
				return JSON.stringify(str);
			} else {
				str += "";
				return str;
			}
		}
	}

	/**
	 * 比较两个值是否一致
	 * @param {object} str
	 * @param {object} val
	 * @returns {boolean}
	 */
	equals(str, val) {
		return str === val;
	}

	/**
	 * 将字符串中不能直接当成正则的字符前边加上\(斜杠)
	 * @param str
	 * @returns {*}
	 */
	symbolReg(str) {
		for (let i = 0; i < this[regExpSymbol].length; i++) {
			if (str.indexOf(this[regExpSymbol][i]) >= 0) {
				let reg = new RegExp("\\" + this[regExpSymbol][i], "gi");
				let temp = "\\" + this[regExpSymbol][i];
				str = str.replace(reg, temp);
			}
		}
		return str;
	}

	/**
	 * 替换所有的指定字符(可做搜索的高亮显示)
	 * @param {string} str 字符
	 * @param {string} replaceStr 需要替换的字符
	 * @param {string} targetStr  替换的目标字符(不传入则为replaceStr)
	 * @returns  string
	 */
	replace(str, replaceStr, targetStr) {
		targetStr = targetStr || replaceStr;
		let newStr = this.symbolReg(replaceStr);
		let reg = new RegExp(newStr, "gi");
		return str.replace(reg, targetStr);
	}

	/**
	 * 随机生成hash字符串
	 * @param {number} hashLength 长度默认24
	 * @param {string} prefix 前缀
	 * @returns {string}
	 */
	hashRandom(hashLength, prefix) {
		prefix = this[headerStr](prefix);
		// 默认长度 24
		return prefix + Array.from(Array(Number(hashLength) || 24), () => Math.floor(Math.random() * 36).toString(36)).join('');
	}

	/**
	 * 返回指定字符串的哈希字符串
	 * @param {string} str
	 * @returns {number}
	 */
	hashStr(str) {
		str = this[headerStr](str);
      let hash = 5381;
      let i = str.length - 1;

		if (typeof str == 'string') {
			for (; i > -1; i--)
				hash += (hash << 5) + str.charCodeAt(i);
		} else {
			for (; i > -1; i--)
				hash += (hash << 5) + str[i];
		}
      let value = hash & 0x7FFFFFFF;

      let retValue = '';
		do {
			retValue += I64BIT_TABLE[value & 0x3F];
		}
		while (value >>= 6);

		return retValue;
	}

	/**
	 * 返回指定字符串的哈希码
	 * @param {string} str
	 * @param {boolean} caseSensitive 是否转换成小写
	 * @returns {number}
	 */
	hashCode(str, caseSensitive) {
		str = this[headerStr](str);
		if (!caseSensitive) {
			str = str.toLowerCase();
		}
		// 1315423911=b'1001110011001111100011010100111'
		let hash = 1315423911, i, ch;
		for (i = str.length - 1; i >= 0; i--) {
			ch = str.charCodeAt(i);
			hash ^= ((hash << 5) + ch + (hash >> 2));
		}
		return (hash & 0x7FFFFFFF);
	}

	/**
	 * 清除两边所有的空格
	 * @param {string} str
	 * @param {boolean} isTab 是否清除所有的回车，tab符
	 * @returns string
	 */
	trim(str, isTab) {
		str = this[headerStr](str);
		if (isTab) {
			return str.replace(/(^\s+|\s+$|\t|\n|\r)/g, "");
		} else {
			return str.replace(/(^\s+|\s+$)/g, "");
		}
	}

	/**
	 * 清除左边所有的空格
	 * @param {string} str
	 * @param {boolean} isTab 是否清除所有的回车，tab符
	 * @returns string
	 */
	trimL(str, isTab) {
		str = this[headerStr](str);
		if (isTab) {
			return str.replace(/(^\s*|\t|\n|\r)/g, "");
		} else {
			return str.replace(/(^\s*)/g, "");
		}
	}

	/**
	 * 清除右边所有的空格
	 * @param {string} str
	 * @param {boolean} isTab 是否清除所有的回车，tab符
	 * @returns string
	 */
	trimR(str, isTab) {
		str = this[headerStr](str);
		if (isTab) {
			return str.replace(/(\s*$|\t|\n|\r)/g, "");
		} else {
			return str.replace(/(\s*$)/g, "");
		}
	}

	/**
	 * 清除所有的空格
	 * @param {string} str
	 * @param {boolean} isTab 是否清除所有的回车，tab符
	 * @returns string
	 */
	trimAll(str, isTab) {
		str = this[headerStr](str);
		if (isTab) {
			return str.replace(/(\s*|\t|\n|\r)/g, "");
		} else {
			return str.replace(/(\s*)/g, "");
		}
	}
}

let stringTools = StringTools.getInstance();
export default stringTools;